package me.whily.hee.util;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Hashtable;

/**
 * 对象操作工具类
 * @author 
 * @version 1.0
 * @date 2012-11-28 10:54:02
 */
public class ObjectUtil {
	
	/**
	 * 克隆对象（支持复杂对象）
	 * @param obj
	 * @return
	 * @throws Exception
	 */
	public static Object cloneObject(Object obj) throws Exception{
		 ByteArrayOutputStream byteOut = null;
		 ObjectOutputStream out = null;
		 ByteArrayInputStream byteIn = null;
		 ObjectInputStream in = null;
		try{
			byteOut = new ByteArrayOutputStream(); 
			out = new ObjectOutputStream(byteOut); 
			out.writeObject(obj); 
			byteIn = new ByteArrayInputStream(byteOut.toByteArray()); 
			in =new ObjectInputStream(byteIn);
			return in.readObject();
		}catch(Exception e){
			throw e;
		}finally{
			if(byteOut != null){
				try{
					byteOut.close();
					byteOut = null;
				}catch(Exception e){}
			}
			if(out != null){
				try{
					out.close();
					out = null;
				}catch(Exception e){}
			}
			if(byteIn != null){
				try{
					byteIn.close();
					byteIn = null;
				}catch(Exception e){}
			}
			if(in != null){
				try{
					in.close();
					in = null;
				}catch(Exception e){}
			}
		}        
	}
	
	/**
	 * 如果字符串为null，则返回空。不为空，则trim。
	 * @param str
	 * @return
	 */
	public static String trimStr(String str){
		if(str == null){
			return "";
		}
		return str.trim();
	}
	
	/**
	 * 把实现序列化接口的对象转为二进制（不包括静态或临时属性的值）
	 * @param obj 待转化对象
	 * @return 字节数组
	 * @author shoujie
	 */
	public static byte[] convertObjToByteArray(Object obj){
		if(obj == null) return null;
		//字节输出流
		ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
		//对象输出流
		ObjectOutputStream objOut = null;
		//把对象写到字节输出流
		try {
			objOut = new ObjectOutputStream(byteOut);
			objOut.writeObject(obj);
		} catch (IOException e) {
		} finally {
			if(objOut != null){
				try {
					objOut.close();
				} catch (IOException e) {
				}
			}
		}
		//从字节输出流中获取字节数组
		byte[] bt = byteOut.toByteArray();
		
		try {
			byteOut.close();
		} catch (IOException e) {
			
		}
		//返回字节数组
		return bt;
		
		
	}
	
	/**
	 * 把字节数组里面的二进制数据转化为对象
	 * @param buf
	 * @return
	 * @author shoujie 
	 */
	public static Object convertByteArrayToObj(byte[] buf){
		if(buf == null) return null;
		//字节输入流
		ByteArrayInputStream byteIn = new ByteArrayInputStream(buf);
		//对象输入流
		ObjectInputStream objIn = null;
		Object obj = null;
		try {
			objIn = new ObjectInputStream(byteIn);
			obj = objIn.readObject();
		} catch (Exception e) {
		} finally {
			if(objIn != null){
				try {
					objIn.close();
				} catch (IOException e) {
				}
			}
		}
		
		try {
			byteIn.close();
		} catch (IOException e) {
		}
		
		return obj;
	}
		
		
	/**把src的部分属性值取出来赋值给dst。
	 * @param src
	 * @param dst
	 * @param params	属性列表，多个属性之间用分号或逗号隔开。属性名大小写不敏感
	 * @throws Exception
	 */
	public static void copyProperties(Object src, Object dst, String params) throws Exception{
		try{
			params = StringUtils.trim(params);
			String[] ps = params.split(";|,");
			if(ps == null || ps.length <= 0){
				throw new Exception("params is null or empty");
			}
			//获取所有可用属性
			ArrayList<String> list_param = new ArrayList<String>();
			for(int i=0;i<ps.length;i++){
				String param = StringUtils.trim(ps[i].toLowerCase());
				if(param.length()<=0){
					continue;
				}
				list_param.add(param);
			}
			if(list_param.size() <= 0){
				throw new Exception("params is null or empty");
			}
			Hashtable<String,Method> hash_getMethod = new Hashtable<String,Method>();
			Method[] methods = src.getClass().getMethods();
			for(int i=0;i<methods.length;i++){
				String name =  methods[i].getName();
				String tmp = "";
				if (name.startsWith("get")){
					tmp = name.substring(3).toLowerCase();				
				}  else if(name.startsWith("is")){
					tmp = name.substring(2).toLowerCase();
				} else{
					continue;
				}
				if(tmp.length()>0){
					if(list_param.contains(tmp)){
						if(methods[i].getParameterTypes()==null || methods[i].getParameterTypes().length<=0){
							hash_getMethod.put(tmp, methods[i]);
						}
					}
				}
			}
			if(hash_getMethod.size() != list_param.size()){
				throw new Exception("Src doesn't have all get method");
			}
			
			Hashtable<String,Method> hash_setMethod = new Hashtable<String,Method>();
			methods = dst.getClass().getMethods();
			for(int i=0;i<methods.length;i++){
				String name =  methods[i].getName();
				String tmp = "";
				if (name.startsWith("set")){
					tmp = name.substring(3).toLowerCase();
				}else{
					continue;
				}
				if(tmp.length()>0){
					if(list_param.contains(tmp)){
						if(methods[i].getParameterTypes()!=null && methods[i].getParameterTypes().length == 1){
							hash_setMethod.put(tmp, methods[i]);
						}
					}
				}
			}
			if(hash_setMethod.size()!=list_param.size()){
				throw new Exception("Dst doesn't have all set method");
			}
			
			for(int i=0;i<list_param.size();i++){
				Method m1 = hash_getMethod.get(list_param.get(i));
				Method m2 = hash_setMethod.get(list_param.get(i));
				m2.invoke(dst, new Object[]{m1.invoke(src)});					
			}
		}catch(Exception e){
			throw e;
		}
	}
        
        /**
         * 把src的部分属性值取出来转换成Object[]，按params的字段顺序。
         * @param src 目标对象
         * @param params src的属性，;|,分隔
         * @param start 返回的String[]第1个元素str[0]，如果不设置第一个元素设为null即可
         * @return
         * @throws Exception 
         */
	public static String[] convertObjToStrByProperties(Object src, String params, Integer start) throws Exception{
            String[] strs = null;
            try{
                    params = StringUtils.trim(params);
                    String[] ps = params.split(";|,");
                    if(ps == null || ps.length <= 0){
                            throw new Exception("params is null or empty");
                    }
                    //获取所有可用属性
                    ArrayList<String> list_param = new ArrayList<>();
                for (String p : ps) {
                    String param = StringUtils.trim(p.toLowerCase());
                    if(param.length()<=0){
                        continue;
                    }
                    list_param.add(param);
                }
                int size = list_param.size();
                    if(size <= 0){
                            throw new Exception("params is null or empty");
                    }
                    Hashtable<String,Method> hash_getMethod = new Hashtable<String,Method>();
                    Method[] methods = src.getClass().getMethods();
                    for(int i=0;i<methods.length;i++){
                            String name =  methods[i].getName();
                            String tmp = "";
                            if (name.startsWith("get")){
                                    tmp = name.substring(3).toLowerCase();				
                            }  else if(name.startsWith("is")){
                                    tmp = name.substring(2).toLowerCase();
                            } else{
                                    continue;
                            }
                            if(tmp.length()>0){
                                    if(list_param.contains(tmp)){
                                            if(methods[i].getParameterTypes()==null || methods[i].getParameterTypes().length<=0){
                                                    hash_getMethod.put(tmp, methods[i]);
                                            }
                                    }
                            }
                    }
                    if(hash_getMethod.size() != size){
                            throw new Exception("Src doesn't have all get method");
                    }
                    if (start != null) {
                         strs = new String[size + 1];
                         strs[0] = start.toString();
                         for(int i=0;i<size;i++){
                                Method m1 = hash_getMethod.get(list_param.get(i));
                                strs[i + 1] = toString(m1.invoke(src));
                        }
                    } else {
                        strs = new String[size];
                        for(int i=0;i<size;i++){
                            Method m1 = hash_getMethod.get(list_param.get(i));
                            strs[i] = toString(m1.invoke(src));
                        }
                    }
            }catch(Exception e){
                    throw e;
            }
            return strs;
	}
        
        /**
         * Boolean 是|否
         * @param obj
         * @return 
         */
        public static String toString(Object obj) {
            if (obj == null) {
                return "";
            } else if (obj instanceof Boolean) {
                return ((Boolean)obj).compareTo(Boolean.TRUE) == 0 ? "是" : "否";
            } else {
                return obj.toString();
            }
        }
}
